<template>
  <div class="file-upload-container">
    <!-- 上传区域 -->
    <el-upload
      ref="upload"
      :action="uploadUrl"
      :headers="headers"
      :multiple="multiple"
      :limit="limit"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-exceed="handleExceed"
      :on-remove="handleRemove"
      :show-file-list="false"
      :disabled="disabled"
      class="uploader"
    >
      <el-button size="small" type="primary">{{ buttonText }}</el-button>
      <div slot="tip" class="el-upload__tip" v-if="showTip">
        支持上传 {{ accept.join(', ') }} 格式文件
        <template v-if="maxSize">，单个文件不超过 {{ maxSize }}MB</template>
      </div>
    </el-upload>

    <!-- 文件列表 -->
    <div class="file-list">
      <div v-for="(file, index) in fileList" :key="file.fileId" class="file-item">
        <div class="file-info" @click="handlePreview(file)">
          <i :class="['file-icon', getFileIcon(file.fileOriginName)]"></i>
          <span class="file-name" :title="file.fileOriginName">{{ getFileName(file.fileOriginName) }}</span>
        </div>

        <div class="file-actions">
          <el-tooltip content="下载" placement="top">
            <el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(file)"></el-button>
          </el-tooltip>
          <el-tooltip content="删除" placement="top" v-if="!disabled">
            <el-button size="mini" type="text" icon="el-icon-delete" @click="handleRemove(file, index)"></el-button>
          </el-tooltip>
        </div>
      </div>
    </div>

    <!-- 预览对话框 -->
    <el-dialog
      v-if="previewType !== 'office' && previewType !== 'pdf'"
      :title="previewTitle"
      :visible.sync="previewVisible"
      width="80%"
      top="5vh"
      :close-on-click-modal="false"
      append-to-body
    >
      <div class="preview-container">


        <!-- PDF预览 - 使用浏览器内置PDF查看器 -->
        <embed
          v-if="!previewType === 'pdf'"
          :src="previewUrl"
          type="application/pdf"
          style="width:100%;height:70vh;"
        />

<!--        &lt;!&ndash; Office文件预览 &ndash;&gt;-->
<!--        <iframe-->
<!--          v-else-if="previewType === 'office'"-->
<!--          :src="previewUrl"-->
<!--          frameborder="0"-->
<!--          style="width:100%;height:70vh"-->
<!--        ></iframe>-->

        <!-- 图片预览 -->
          <el-image
            v-else-if="previewType === 'image'"
            style="width: 100%; height: 70vh"
            :src="previewUrl"
            :preview-src-list="[previewUrl]"
            fit="contain">
          </el-image>
<!--        <img-->
<!--          :src="previewUrl"-->
<!--          style="max-width: 100%; max-height: 70vh;-->
<!--          display: block; margin: 0 auto;"-->
<!--          alt=""-->
<!--          v-else-if="previewType === 'image'">-->

        <!-- 不支持预览的提示 -->
        <div v-else class="unsupported-preview">
          <i class="el-icon-warning"></i>
          <span>该文件类型不支持预览</span>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {getToken} from '@/utils/auth'
import {delFile, getFile, previewFile} from "@/api/files/file";
import Viewer from 'viewerjs';
import 'viewerjs/dist/viewer.css';
import {Message} from "element-ui";

export default {
  name: 'FileUploadPlus',
  props: {
    value: {type: [Array, Object], default: () => []},
    limit: {type: Number, default: 5},
    maxSize: {type: Number, default: 10}, // MB
    accept: {type: Array, default: () => ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'jpg', 'jpeg', 'png']},
    buttonText: {type: String, default: '上传文件'},
    multiple: {type: Boolean, default: true},
    disabled: {type: Boolean, default: false},
    showTip: {type: Boolean, default: true},
    isPublic: {type: Boolean, default: false}
  },
  data() {
    return {
      uploadUrl: process.env.VUE_APP_BASE_API + '/file/upload',
      headers: {Authorization: 'Bearer ' + getToken()},
      fileList: [],
      previewVisible: false,
      previewUrl: '',
      previewTitle: '',
      previewType: ''
    }
  },
  watch: {
    value: {
      immediate: true,
      deep: true,
      handler(val) {
        this.initFileList(val)
      }
    }
  },
  methods: {

    initFileList(val) {

      if (!val || (Array.isArray(val) && val.length === 0)) {
        this.fileList = []
        return
      }

      if (Array.isArray(val)) {
        this.fileList = val.map(item => ({
          // 确保ID转为字符串
          fileId: String(item.fileId),
          fileUrl: item.fileUrl,
          fileOriginName: item.fileOriginName,
          fileType: item.fileType
        }))
      } else {
        this.fileList = [{
          fileId: String(val.fileId),
          fileUrl: val.fileUrl,
          fileOriginName: val.fileOriginName,
          fileType: val.fileType
        }]
      }
    },

    // 获取文件图标
    getFileIcon(fileName) {
      const ext = fileName.split('.').pop().toLowerCase()
      if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext)) return 'el-icon-picture'
      if (['pdf'].includes(ext)) return 'el-icon-document'
      if (['mp3', 'wav'].includes(ext)) return 'el-icon-headset'
      if (['mp4', 'avi', 'mov'].includes(ext)) return 'el-icon-video-camera'
      return 'el-icon-document'
    },

    // 获取简短文件名
    getFileName(fileName) {
      if (fileName.length > 20) {
        return `${fileName.substring(0, 8)}...${fileName.substring(fileName.lastIndexOf('.'))}`
      }
      return fileName
    },

    // 上传前校验
    beforeUpload(file) {
      const fileExt = file.name.split('.').pop().toLowerCase()
      const isValidType = this.accept.includes(fileExt)

      if (!isValidType) {
        this.$message.error(`只能上传 ${this.accept.join(', ')} 格式文件`)
        return false
      }

      const isLtSize = file.size / 1024 / 1024 < this.maxSize
      if (!isLtSize) {
        this.$message.error(`文件大小不能超过 ${this.maxSize}MB`)
        return false
      }

      return true
    },

    handleSuccess(response, file) {
      console.log('上传回调=========》', response)
      if (response.code === 200) {
        // 确保response.data是数组
        const fileData = Array.isArray(response.data) ? response.data : [response.data]

        const newFiles = fileData.map(item => ({
          // 将Long类型ID转为字符串保存，避免精度丢失
          fileId: String(item.fileId),
          fileUrl: item.fileUrl,
          fileOriginName: item.fileOriginName || file.name,
          fileType: item.fileType || file.name.split('.').pop().toLowerCase()
        }))

        if (this.multiple) {
          this.fileList = [...this.fileList, ...newFiles]
        } else {
          this.fileList = newFiles.slice(0, 1)
        }

        this.emitValue()
        this.$emit('success', newFiles)
        this.$message.success('上传成功')
      } else {
        this.$message.error(response.msg || '上传失败')
        this.$emit('error', response)
      }
    },

    // 上传错误处理
    handleError(error) {
      this.$message.error('上传失败')
      this.$emit('error', error)
    },

    // 超出限制处理
    handleExceed() {
      this.$message.warning(`最多只能上传 ${this.limit} 个文件`)
    },

    handleRemove(file, index) {
      this.$confirm('确定要删除该文件吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        try {
          // 确保fileId存在（已经是字符串形式）
          console.log('要删除的文件:', file)
          if (!file.fileId) {
            throw new Error('文件ID不存在')
          }

          // 直接将字符串ID传给后端（Spring会自动转换）
          await delFile(file.fileId)

          if (typeof index === 'number') {
            this.fileList.splice(index, 1)
          } else {
            this.fileList = this.fileList.filter(item => item.fileId !== file.fileId)
          }
          this.emitValue()
          this.$message.success('删除成功')
        } catch (error) {
          console.error('删除文件失败:', error)
          this.$message.error(error.message || '删除失败')
        }
      }).catch(() => {
        // 取消删除
      })
    },

    // 预览文件
    async handlePreview(file) {
      console.log('预览文件:', file)
      const ext = file.fileType.toLowerCase();
      this.previewTitle = file.fileOriginName;

      // 图片预览（通过blob方式）
      if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(ext)) {
        this.previewVisible = true; // 确保打开弹窗
        this.previewType = 'image';
        try {
          // 释放之前的URL
          if (this.previewUrl.startsWith('blob:')) {
            URL.revokeObjectURL(this.previewUrl);
          }

          // 通过axios获取文件blob
          const response = await getFile(file.fileId); // 添加await
          const blob = new Blob([response], { type: 'image/*' }); // 简化type
          this.previewUrl = URL.createObjectURL(blob); // 使用previewUrl
        } catch (error) {
          this.$message.error('图片预览失败');
          console.error('图片预览错误:', error);
          this.previewVisible = false; // 出错时关闭弹窗
        }
        return;
      }

      // PDF文件预览
      if (ext === 'pdf') {
        // this.previewType = 'pdf'
        // this.previewUrl = file.fileUrl
        // this.previewVisible = true
        // 通过axios获取文件blob
        // 处理链接逻辑
        getFile(file.fileId)
          .then(response => {
            const blobUrl = URL.createObjectURL(new Blob([response], {type: 'application/pdf'}));

            const iframe = document.createElement('iframe');
            iframe.src = blobUrl;
            iframe.style.width = '100%';
            iframe.style.height = '100%';

            const previewWindow = window.open('', '_blank');
            previewWindow.document.body.appendChild(iframe);

            new Viewer(previewWindow.document.body, {
              inline: true,
              toolbar: {
                zoomIn: true,
                zoomOut: true,
                rotateLeft: true,
                rotateRight: true,
              },
            });
          })
          .catch(error => {
            console.error('Error handling link:', error);
            Message.error('文件预览失败');
          });

        return
      }

      // Office文件预览
      if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(ext)) {
        this.previewType = 'office'
        if (this.isPublic) {
          this.previewUrl = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(file.fileUrl)}`
        } else {
          // 处理链接逻辑
          previewFile(file.fileId)
            .then(response => {
              const blobUrl = URL.createObjectURL(new Blob([response], {type: 'application/pdf'}));

              const iframe = document.createElement('iframe');
              iframe.src = blobUrl;
              iframe.style.width = '100%';
              iframe.style.height = '100%';

              const previewWindow = window.open('', '_blank');
              previewWindow.document.body.appendChild(iframe);

              new Viewer(previewWindow.document.body, {
                inline: true,
                toolbar: {
                  zoomIn: true,
                  zoomOut: true,
                  rotateLeft: true,
                  rotateRight: true,
                },
              });
            })
            .catch(error => {
              console.error('Error handling link:', error);
              Message.error('文件预览失败');
            });
        }
        // this.previewVisible = true
        return
      }

      // 其他文件类型提示不支持预览
      this.$message.warning('该文件类型不支持预览')
    },

    // 组件销毁时释放资源
    beforeDestroy() {
      if (this.imagePreviewUrl) {
        URL.revokeObjectURL(this.imagePreviewUrl);
      }
    },

    //下载方法
    async handleDownload(file) {
      try {
        const response = await getFile(file.fileId)
        const blob = new Blob([response], { type: response.type })

        // 创建下载链接
        const downloadUrl = URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = file.fileOriginName // 使用原始文件名
        link.style.display = 'none'

        document.body.appendChild(link)
        link.click()

        // 清理资源
        document.body.removeChild(link)
        URL.revokeObjectURL(downloadUrl)
      } catch (error) {
        console.error('文件下载失败:', error)
        this.$message.error('文件下载失败，请稍后重试')

        // 处理blob类型的错误响应（如果后端返回JSON错误信息）
        if (error.response.data instanceof Blob) {
          const reader = new FileReader()
          reader.onload = () => {
            try {
              const errorData = JSON.parse(reader.result)
              this.$message.error(errorData.message || '下载请求错误')
            } catch (e) {
              this.$message.error('文件下载失败')
            }
          }
          reader.readAsText(error.response.data)
        }
      }
    },


    // 触发更新事件
    emitValue() {
      if (this.multiple) {
        this.$emit('input', this.fileList)
        this.$emit('change', this.fileList)
      } else {
        const value = this.fileList[0] || null
        this.$emit('input', value)
        this.$emit('change', value)
      }
    },

    // 清空文件列表
    clearFiles() {
      this.fileList = []
      this.emitValue()
    },

    // 手动提交上传
    submit() {
      this.$refs.upload.submit()
    }
  }
}
</script>

<style lang="scss" scoped>
.file-upload-container {
  width: 100%;

  .uploader {
    display: inline-block;
    margin-bottom: 10px;
  }

  .el-upload__tip {
    font-size: 12px;
    color: #909399;
    margin-top: 8px;
  }

  .file-list {
    border: 1px solid #ebeef5;
    border-radius: 4px;
    padding: 10px;

    .file-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 8px 10px;
      border-radius: 4px;
      transition: background-color 0.3s;

      &:hover {
        background-color: #f5f7fa;
      }

      .file-info {
        display: flex;
        align-items: center;
        flex: 1;
        cursor: pointer;
        overflow: hidden;

        .file-icon {
          margin-right: 8px;
          font-size: 20px;
          color: #409EFF;
        }

        .file-name {
          flex: 1;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }

      .file-actions {
        flex-shrink: 0;
        margin-left: 10px;
      }
    }
  }

  .preview-container {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 60vh;

    .demo-image__preview {
      width: 100%;
      text-align: center;
    }

    .unsupported-preview {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #909399;

      .el-icon-warning {
        font-size: 50px;
        margin-bottom: 20px;
      }
    }
  }
}

</style>
